home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Utilities / Winter Shell 1.0d2 / Source / Libraries / EventLib / EventUtilLib.c < prev   
Encoding:
C/C++ Source or Header  |  1994-01-20  |  7.7 KB  |  278 lines  |  [TEXT/KAHL]

  1. /*
  2.     94/01/05 aih
  3.     - added pre-event task list
  4.     
  5.     94/01/02 aih
  6.     - uses PointerFixedLib to allocate the event structures, which is more
  7.     efficient than using the memory manager (I don't use handles since
  8.     they'd be less efficient than pointers)
  9.      
  10.     93/12/17 aih
  11.     - changed to use LLPtrLib to avoid duplicating linked-list code
  12.     
  13.     93/10/18 aih
  14.     - major revisions to support new event handling method
  15.     - added focuslist to windows
  16.     
  17.     93/03/12 Ari Halberstadt (AIH)
  18.     - Split into a separate file from EventLib and WindowLib */
  19.  
  20. #include "EventPrivateLib.h"
  21. #include "PointerFixedLib.h"
  22. #include "WindowLib.h"
  23.  
  24. /*----------------------------------------------------------------------------*/
  25. /* validation */
  26. /*----------------------------------------------------------------------------*/
  27.  
  28. /* true if the object is valid */
  29. Boolean EventObjectValid(EventObjectType object)
  30. {
  31.     return(true);
  32. }
  33.  
  34. /* true if the event item is valid */
  35. Boolean EventValid(EventType *event)
  36. {
  37.     if (! PtrFixedValidSize(event, sizeof(EventType))) return(false);
  38.     if (! event->table) return(false);
  39.     if (! EventObjectValid(event->object)) return(false);
  40.     return(true);
  41. }
  42.  
  43. /*----------------------------------------------------------------------------*/
  44. /* maintaining object focus */
  45. /*----------------------------------------------------------------------------*/
  46.  
  47. static WindowPtr gFocusWindow = NULL;
  48.  
  49. /* set the object with the input focus */
  50. void FocusSet(EventObjectType object)
  51. {
  52.     EventType *focus = NULL;
  53.     EventType *unfocus = NULL;
  54.     
  55.     require(WinValid(FocusWindow()));
  56.     unfocus = WinFocus(FocusWindow());
  57.     WinFocusSet(FocusWindow(), object);
  58.     focus = WinFocus(FocusWindow());
  59.     if (focus != unfocus) {
  60.         if (unfocus) EventFocus(unfocus, false);
  61.         if (focus) EventFocus(focus, true);
  62.         EventAdjustMenu();
  63.     }
  64. }
  65.  
  66. /* set window with input focus */
  67. void FocusWindowSet(WindowPtr window)
  68. {
  69.     gFocusWindow = window;
  70. }
  71.  
  72. /* return window with input focus */
  73. WindowPtr FocusWindow(void)
  74. {
  75.     return(gFocusWindow);
  76. }
  77.  
  78. /* return first object in focus window's object list */
  79. EventType *FocusList(void)
  80. {
  81.     return(FocusWindow() ? WinObjects(FocusWindow()) : NULL);
  82. }
  83.  
  84. /* return event object with input focus */
  85. static EventType *FocusEvent(void)
  86. {
  87.     return(FocusWindow() ? WinFocus(FocusWindow()) : NULL);
  88. }
  89.  
  90. /* return object with input focus */
  91. EventObjectType FocusObject(void)
  92. {
  93.     return(FocusEvent() ? FocusEvent()->object : NULL);
  94. }
  95.  
  96. /* return id of object with input focus */
  97. EventIDType FocusID(void)
  98. {
  99.     return(FocusEvent() ? FocusEvent()->id : 0);
  100. }
  101.  
  102. /* return event handler table of object with input focus */
  103. const EventTableType *FocusTable(void)
  104. {
  105.     return(FocusEvent() ? FocusEvent()->table : NULL);
  106. }
  107.  
  108. /*----------------------------------------------------------------------------*/
  109. /* maintaining event lists */
  110. /*----------------------------------------------------------------------------*/
  111.  
  112. /* find the object with the specified id */
  113. EventType *EventFindID(EventType *list, EventIDType id)
  114. {
  115.     while (list && list->id != id)
  116.         list = EventNext(list);
  117.     return(list);
  118. }
  119.  
  120. /* find the object and return previous item as well */
  121. static void EventFindObjectPrevious(EventType *list, EventObjectType object,
  122.     EventType **item, EventType **previous)
  123. {
  124.     register EventType *p;
  125.     
  126.     require(! list || EventValid(list));
  127.     require(EventObjectValid(object));
  128.     *previous = NULL;
  129.     for (p = list; p; p = EventNext(p)) {
  130.         if (p->object == object)
  131.             break;
  132.         *previous = p;
  133.     }
  134.     *item = p;
  135. }
  136.  
  137. /* find the object */
  138. EventType *EventFindObject(EventType *list, EventObjectType object)
  139. {
  140.     while (list && list->object != object)
  141.         list = EventNext(list);
  142.     return(list);
  143. }
  144.  
  145. /* insert the object before the head of the list */
  146. EventType *EventInsert(EventType *list, EventObjectType object,
  147.     const EventTableType *table)
  148. {
  149.     EventType *new = NULL;
  150.  
  151.     require(! list || EventValid(list));
  152.     require(EventObjectValid(object));
  153.     new = PtrFixedBegin(sizeof(EventType));
  154.     memclr(new, sizeof(EventType));
  155.     new->object = object;
  156.     new->table = table;
  157.     check(new->table != NULL);
  158.     ensure(EventValid(new));
  159.     return(LLPInsert(list, new));
  160. }
  161.  
  162. /* append the object after the tail of the list */
  163. EventType *EventAppend(EventType *list, EventObjectType object,
  164.     const EventTableType *table)
  165. {
  166.     return(LLPAppend(list, EventInsert(NULL, object, table)));
  167. }
  168.  
  169. /* delete the object from the list */
  170. EventType *EventDelete(EventType *list, EventObjectType object)
  171. {
  172.     EventType *item, *previous;
  173.     
  174.     EventFindObjectPrevious(list, object, &item, &previous);
  175.     list = LLPDeleteFast(list, item, previous);
  176.     PtrFixedEnd(item);
  177.     return(list);
  178. }
  179.  
  180. /* move object to head of list */
  181. EventType *EventMoveToFront(EventType *list, EventObjectType object)
  182. {
  183.     EventType *item, *previous;
  184.     
  185.     EventFindObjectPrevious(list, object, &item, &previous);
  186.     return(LLPInsert(LLPDeleteFast(list, item, previous), item));
  187. }
  188.  
  189. /*----------------------------------------------------------------------------*/
  190. /* using the event table which stores the event handlers for each type of
  191.     object */
  192. /*----------------------------------------------------------------------------*/
  193.  
  194. #define MAX_EVENT (64)
  195.  
  196. static struct {
  197.     const EventTableType *table[MAX_EVENT];
  198.     short ntables;
  199. } gEventTable;
  200.  
  201. /* Register the object's event handlers into the event function table.
  202.     The table must be a pointer to permanent memory, e.g., static
  203.     or allocated in the heap.  */
  204. void EventTableRegister(const EventTableType *table)
  205. {
  206.     require(gEventTable.ntables < MAX_EVENT);
  207.     gEventTable.table[gEventTable.ntables++] = table;
  208. }
  209.  
  210. /* return number of event tables */
  211. short EventTableCount(void)
  212. {
  213.     return(gEventTable.ntables);
  214. }
  215.  
  216. /* return the i'th event table */
  217. const EventTableType *EventTableGet(short i)
  218. {
  219.     require(0 <= i && i < gEventTable.ntables);
  220.     return(gEventTable.table[i]);
  221. }
  222.  
  223. /*----------------------------------------------------------------------------*/
  224. /* There are two task lists: one is executed before the next event
  225.     is retrieved, the other is executed after each event has been processed. 
  226.     The order of execution of tasks in a particular task list is unspecified.
  227.     Once installed, tasks are executed until they are removed from the task list.
  228.     For tasks that execute only once, you will typically remove the task from
  229.     within the task handler (the task delete function can be called at any
  230.     time).
  231.     
  232.     Since it is not always possible to predict exactly when a task handler
  233.     will be executed (for instance, if an exception occurs during the
  234.     processing of an event), care must be taken to ensure that the object
  235.     processed by the task is still in existence when the task is executed.
  236.     One way to achieve this is to add a task field to the object and set that
  237.     field to the task handle returned by the task insert function. In the
  238.     object's disposal routine, simply call the task delete function before
  239.     disposing of the object. Since the task will have been deleted, it will
  240.     no longer be executed, and there is no possibility of using the disposed
  241.     object in the task. */
  242. /*----------------------------------------------------------------------------*/
  243.  
  244. static TaskHandle gEventPreTasks;    /* tasks executed before the next event */
  245. static TaskHandle gEventPostTasks;    /* tasks executed after the next event */
  246.  
  247. TaskHandle EventPreTaskInsert(TaskActionType action, void *data)
  248. {
  249.     gEventPreTasks = TaskInsert(gEventPreTasks, action, data);
  250.     return(gEventPreTasks);
  251. }
  252.  
  253. void EventPreTaskDelete(TaskHandle task)
  254. {
  255.     gEventPreTasks = TaskDelete(gEventPreTasks, task);
  256. }
  257.  
  258. void EventPreTasksExecute(void)
  259. {
  260.     TasksExecute(gEventPreTasks);
  261. }
  262.  
  263. TaskHandle EventPostTaskInsert(TaskActionType action, void *data)
  264. {
  265.     gEventPostTasks = TaskInsert(gEventPostTasks, action, data);
  266.     return(gEventPostTasks);
  267. }
  268.  
  269. void EventPostTaskDelete(TaskHandle task)
  270. {
  271.     gEventPostTasks = TaskDelete(gEventPostTasks, task);
  272. }
  273.  
  274. void EventPostTasksExecute(void)
  275. {
  276.     TasksExecute(gEventPostTasks);
  277. }
  278.